#!/bin/sh
##HISTORY
# 2013-06-18 - Al C - started!
# 2013-07-08 - Al C - version 1.0 ready!
# 2013-07-09 - Al C - version 1.0.1 - fixed path to config file if not passed as a parameter
# 2013-07-11 - Al C - version 1.0.2 - improvements in web UI; nothing interesting here
# 2013-07-13 - Al C - version 1.0.3 - added loglevel
# 2013-07-17 - Al C - version 1.0.4 - tweaks to the web UI
# 2013-07-18 - Al C - version 1.0.5 - integer overflow issues
# 2013-07-18 - Al C - version 1.0.6 - a different fix for integer; new IP matching fix; hourly report and beginnings of live usage data
# 2013-07-25 - Al C - version 1.0.7 - added useBC option to config.file and calculation as another attempt to fix the integer overflow issue
# 2013-08-02 - Al C - version 1.0.8 - option to compress log files & new process for checking if the script is running
# 2013-09-25 - Al C - version 1.0.10 - tar issues; added config.js; error reporting for copy fails and multiple instances
# 2013-09-25 - Al C - version 1.0.11 - added traff daemon outputs to monthly usage file;fixed regex to parse traff data
# 2013-10-06 - Al C - version 1.0.12 - all changes in the web UI; none in this script
# 2013-10-29 - Al C - version 1.0.13 - changes to startup functions to copy ../Setup/www/ directory to /tmp/www
# 2013-10-29 - Al C - version 1.0.14 - stopped writing IP addresses to usage and hourly files (they're still in the users file); replace older reporting files when upgrading
# 2013-10-29 - Al C - version 1.0.15 - live data finally(?); oh and unlimited usage intervals; plus a lot of changes (improvements?) to the loops (hopefully more efficient now); a second iptable entry for the live data
#defaults
_version='1.0.15'
_savedconfigMd5=''
_configMd5=''
_savedusersMd5=''
_usersMd5=''
_connectedUsers=/proc/net/arp
LAN_IFACE=`nvram get lan_ifname`
ACMON_RULE=ACMON
LIVE_RULE=ACLU
#default parameters - these values may be updated in readConfig()
d_paused=0
d_updatefreq=10
d_updateInterval=3
d_publishInterval=3
d_baseDir="/opt/YAMon/"
d_setupDir="Setup/"
d_setupWebDir="Setup/www/"
d_dataDir="data/"
d_logDir="logs/"
d_wwwPath="/tmp/www/"
d_wwwData="data/"
d_wwwBU="wwwBU/"
d_usageFileName="mac_data.html"
d_usersFileName="users.file"
d_usersFileNameWWW="users.html"
d_configWWW="config.js"
d_enableLogging=1
d_log2file=1
d_loglevel=1
d_ispBillingDay=5
d_doDailyBU=1
d_tarBUs=0
d_doHourlyData=1
d_hourlyFileName="hourly_data.html"
d_doLiveUpdates=0
d_liveFileName="live_data.js"
d_dailyBUPath="daily\ bu/"
d_useBC=0
d_traff_daemon=0
d_unlimited_usage=0
d_unlimited_start="02:00"
d_unlimited_end="08:00"
#globals
_macUsageDB=""
_hourlyUsageDB=""
_liveUsageDB=""
_usersFile=""
_macUsageWWW=""
_usersFileWWW=""
_hourlyFileName=""
_hourlyUsageWWW=""
_usageData=""
_hData=""
_cDay=`date +%d`
_pDay="$_cDay"
_unlimited_usage=""
_unlimited_start=""
_unlimited_end=""

_wwwImages='images/'
_pndDown=0
_pndUp=0
setDefaults()
{
	send2log "=== Check script parameters ===" 0
	if [ -z "$_configFile" ] ; then
		echo 'No parameter specified... assuming config.file'
		_configFile="$d_baseDir"'Setup/config.file'
	fi
	if [ ! -f "$_configFile" ] ; then
		echo 'Unable to start... config file does not exist - '"$_configFile"
		rmdir $_lockDir
		exit 0
	fi
	if [ ! -s "$_configFile" ] ; then
		echo 'Unable to start... config file is zero bytes'
		rmdir $_lockDir
		exit 0
	fi
}
readConfig(){
	[ "$started" = true ] && send2log "=== Read the Configuration file ===" 0
	_configMd5=`md5sum $_configFile | awk '{print $1}'`
	if [ "$_configMd5" != "$_savedconfigMd5" ] ; then
		logString=`cat $_configFile`
		while read row
		do
			eval $row
		done < $_configFile

		send2log "
---------------------------------------
Starting the Yet Another Monitor script
version $_version
=======================================
" 2
		send2log "--- New Configuration Settings ---
$logString
" 2
		if [ -z "$_monitoring" ] || [ "$_monitoring" -eq '0' ] ; then
			send2log "  >>> _monitoring is set to zero... script will not run!" 2
		fi
		if [ -z "$_updatefreq" ] || [ -z "$_updateInterval" ]  || [ -z "$_publishInterval" ] ; then
			send2log '  >>> Problems in config.file... paremeters not set properly... using defaults' 2
		fi
		#if the parameters are missing then set them to the defaults
		[ -z "$_updatefreq" ] && _updatefreq=$d_updatefreq
		[ -z "$_updateInterval" ] && _updateInterval=$d_updateInterval
		[ -z "$_publishInterval" ] && _publishInterval=$d_publishInterval
		[ -z "$_enableLogging" ] && _enableLogging=$d_enableLogging
		[ -z "$_log2file" ] && _log2file=$d_log2file
		[ -z "$_loglevel" ] && _loglevel=$d_loglevel
		[ -z "$_paused" ] && _paused=$d_paused
		[ -z "$_ispBillingDay" ] && _ispBillingDay=$d_ispBillingDay
		[ -z "$_doHourlyData" ] && _doHourlyData=$d_doHourlyData
		[ -z "$_hourlyFileName" ] && _hourlyFileName=$d_hourlyFileName
		[ -z "$_doLiveUpdates" ] && _doLiveUpdates=$d_doLiveUpdates
		[ -z "$_liveFileName" ] && _liveFileName=$d_liveFileName
		[ -z "$_doDailyBU" ] && _doDailyBU=$d_doDailyBU
		[ -z "$_dailyBUPath" ] && _dailyBUPath=$d_dailyBUPath
		[ -z "$_tarBUs" ] && _tarBUs=$d_tarBUs
		[ -z "$_baseDir" ] && _baseDir=$d_baseDir
		[ -z "$_setupDir" ] && _setupDir=$d_setupDir
		[ -z "$_setupWebDir" ] && _setupWebDir=$d_setupWebDir
		[ -z "$_dataDir" ] && _dataDir=$d_dataDir
		[ -z "$_logDir" ] && _logDir=$dlogDir
		[ -z "$_wwwPath" ] && _wwwPath=$d_wwwPath
		[ -z "$_wwwData" ] && _wwwData=$d_wwwData
		[ -z "$_wwwBU" ] && _wwwBU=$d_wwwBU
		[ -z "$_usageFileName" ] && _usageFileName=$d_usageFileName
		[ -z "$_usersFileName" ] && _usersFileName=$d_usersFileName
		[ -z "$_usersFileNameWWW" ] && _usersFileNameWWW=$d_usersFileNameWWW
		[ -z "$_configWWW" ] && _configWWW=$d_configWWW
		[ -z "$_useBC" ] && _useBC=$d_useBC
		[ -z "$_traff_daemon" ] && _traff_daemon=$d_traff_daemon
		[ -z "$_unlimited_usage" ] && _unlimited_usage=$d_unlimited_usage
		[ -z "$_unlimited_start" ] && _unlimited_start=$d_unlimited_start
		[ -z "$_unlimited_end" ] && _unlimited_end=$d_unlimited_end
		_usersFile="$_baseDir$_dataDir$_usersFileName"
		_usersFileWWW="$_wwwPath$_wwwData$_usersFileNameWWW"
		_liveFilePath="$_wwwPath$_liveFileName"
		#Check for directories
		if [ "${_logDir:0:1}" = "/" ] ; then
			lfpath=$_logDir
		else
			lfpath=$_baseDir$_logDir
		fi
		if [ ! -d "$lfpath" ] ; then
			mkdir -p "$lfpath"
			send2log "  >>> Creating logs directory - $lfpath" 1
		fi
		if [ "${_dailyBUPath:0:1}" = "/" ] ; then
			bupath=$_dailyBUPath
		else
			bupath=$_baseDir$_dailyBUPath
		fi
		if [ ! -d "$bupath" ] ; then
			send2log "  >>> Creating Daily BackUp directory - $bupath" 1
			mkdir -p "$bupath"
		fi
		if [ ! -d "$_baseDir$_dataDir" ] ; then
			send2log "  >>> Creating data directory" 1
			mkdir -p "$_baseDir$_dataDir"
		fi
		if [ -z "$_usersFile" ] ; then
			send2log "  >>> Creating empty users file: $_usersFile" 1
			touch $_usersFile
		fi
		if [ ! -d "$_wwwPath$_wwwData" ] ; then
			mkdir -p "$_wwwPath$_wwwData"
			send2log "  >>> Creating web storage directory" 1
		fi
		if [ ! -d "$_baseDir$_wwwBU" ] ; then
			mkdir -p "$_baseDir$_wwwBU"
			send2log "  >>> Creating web BU directory" 1
		fi
		if [ ! -d "$_wwwPath$_wwwImages" ] ; then
			mkdir -p "$_wwwPath$_wwwImages"
			send2log "  >>> Creating web images directory" 1
		fi
		copyfiles "$_baseDir$_setupWebDir*" "$_wwwPath"
		copyfiles "$_baseDir$_dataDir*.html" "$_wwwPath$_wwwData"

		configjs="$_wwwPath$_configWWW"
		if [ -f "$configjs" ] ; then
			rm "$configjs"
		fi
		touch "$configjs"
		echo "_ispBillingDay='$_ispBillingDay'" > $configjs
		echo "_wwwData='$_wwwData'" >> $configjs
		echo "_usageFileName='$_usageFileName'" >> $configjs
		echo "_usersFileNameWWW='$_usersFileNameWWW'" >> $configjs
		echo "_doHourlyData='$_doHourlyData'" >> $configjs
		if [ "$_doHourlyData" -eq "1" ]; then
			echo "_hourlyFileName='$_hourlyFileName'" >> $configjs
		fi
		echo "_doLiveUpdates='$_doLiveUpdates'" >> $configjs
		if [ "$_doLiveUpdates" -eq "1" ]; then
			echo "_luEvery='$_updatefreq'" >> $configjs
			echo "_liveFileName='$_liveFileName'" >> $configjs
		fi
		echo "_unlimited_usage='$_unlimited_usage'" >> $configjs
		if [ "$_unlimited_usage" -eq "1" ]; then
			echo "_unlimited_start='$_unlimited_start'" >> $configjs
			echo "_unlimited_end='$_unlimited_end'" >> $configjs
		fi
		echo "_traff_daemon='$_traff_daemon'" >> $configjs
		_savedconfigMd5="$_configMd5"
	fi
}
copyfiles(){
	src=$1
	dst=$2
	`echo "cp -a $src $dst"`
	res=$?
	pre='  !!!'
	pos=' failed '
	[ "$res" -eq 0 ] && pre='  >>>'
	[ "$res" -eq 0 ] && pos=' successful'
	lvl=`expr $res '+' 1`
	send2log "$pre Copy from $src to $dst$pos" $lvl
}
send2log()
{
	if [ "${_logDir:0:1}" = "/" ] ; then
		lfpath=$_logDir
	else
		lfpath=$_baseDir$_logDir
	fi
	logfilename="$lfpath"'monitor-'`date +%d-%m-%Y`'.log'
	if [ ! -f "$logfilename" ] ; then
		echo `date +%Y-%m-%d`' '`date +%H:%M:%S`': '"
---------------------------------------
YAMon :: version $_version
=======================================
">> $logfilename
	fi
	if [ "$_enableLogging" = "1" ]; then
		[ "$_log2file" = "1" ] || [ "$_log2file" = "2" ] && [ "$2" -ge "$_loglevel" ] && echo `date +%Y-%m-%d`' '`date +%H:%M:%S`': '" $1">> $logfilename
		[ "$_log2file" = "0" ] || [ "$_log2file" = "2" ] && [ "$2" -ge "$_loglevel" ] && echo `date +%Y-%m-%d`' '`date +%H:%M:%S`': '" $1"
	fi
}


setupIPChain()
{
	chain=$1
	send2log "=== setupIPChain for $chain ===" 0
	foundRule=`iptables -L FORWARD | grep -c "$chain"`
	if [ "$foundRule" -eq 0 ]; then
		send2log "  >>> Created rule $chain in chain FORWARD" 2
		iptables -N "$chain"
		iptables -I FORWARD -j "$chain"
	elif [ "$foundRule" -eq 1 ]; then
		send2log "  >>> Rule $chain exists in chain FORWARD" 0
	else
		send2log "  !!! Found $foundRule instances of $chain in chain FORWARD...  (Flushed FORWARD!)" 2
		iptables -F FORWARD
		sleep 5
		iptables -I FORWARD -j "$chain"
	fi
}
checkIP()
{
	chain=$1
	ip=$2
	tb=$3
	nm=`echo "$tb" | grep -c "${ip} " `
	if [ "$nm" -eq "0" ]; then
		send2log "		>>> Added rules to $chain for $ip" 2
		iptables -I "$chain" -d ${ip} -j RETURN
		iptables -I "$chain" -s ${ip} -j RETURN
		nrc=$((nrc+2))
	elif [ "$nm" -eq "2" ]; then
		send2log "	>>> $ip -> $nm" 0
	else
		send2log "	!!! Incorrect number of rules for $ip in $chain -> $nm (Flushed $chain!)" 2
		iptables -F $chain
		#setupIPRules
	fi
}
setupIPRules()
{
	send2log "=== setupIPRules ===" 0
	#check to see if the main monitoring chains exists
	setupIPChain "$ACMON_RULE"
	if [ "$_doLiveUpdates" -eq "1" ] ; then
		setupIPChain "$LIVE_RULE"
	fi

	#For each host in the ARP table
	nrc=0;
	nuc=0
	send2log "  >>> Checked rules & user file entries" 0

	acr=`iptables -nL "$ACMON_RULE"`
	if [ "$_doLiveUpdates" -eq "1" ] ; then
		lur=`iptables -nL "$LIVE_RULE"`
	fi

	while read currentIP type flags currentMAC mask iface
	do
		if [ "$iface" != "$LAN_IFACE" ] ; then continue; fi
		if [ "$currentMAC" == "00:00:00:00:00:00" ] ; then
			send2log "  >>> Null MAC address for $currentIP not added" 0
			continue
		fi
		send2log "  >>> checkIP for $ACMON_RULE" 0
		checkIP "$ACMON_RULE" "$currentIP" "$acr"
		if [ "$_doLiveUpdates" -eq "1" ] ; then
			send2log "  >>> checkIP for $LIVE_RULE" 0
			checkIP "$LIVE_RULE" "$currentIP" "$lur"
		fi

		foundMAC=`echo "$_currentUsers" | grep -i "$currentMAC"`
		foundIP=`echo "$_currentUsers" | grep -i "$currentIP"`
		oldIP=`echo "$foundMAC" | cut -d, -f2`
		#new MAC & IP
		if [ -z "$foundMAC" ] && [ -z "$foundIP" ] ; then
			newuser="$currentMAC,$currentIP,Unknown,Added $currentMAC"
			#append new line to _usersFile
			echo "$newuser" >> $_usersFile
			_currentUsers="$_currentUsers
	$newuser"
			nuc=$((nuc+1))
			send2log "	>>> Added new user: $currentMAC & $currentIP" 1
		#new MAC (& duplicate IP?)
		elif [ -z "$foundMAC" ] ; then
			newuser="$currentMAC,$currentIP,Unknown,Added $currentMAC"
			#append new line to _usersFile
			echo "$newuser" >> $_usersFile
			_currentUsers="$_currentUsers
	$newuser"
			nuc=$((nuc+1))
			send2log "	>>> Added new user: $currentMAC & $currentIP (duplicate IP?)" 1
		#existing MAC (& new IP?)
		elif [ -z "$foundIP" ] || [ "$oldIP" != "$currentIP" ] ; then
			_currentUsers=`echo "$_currentUsers" | sed "s/$currentMAC,$oldIP/$currentMAC,$currentIP/"`
			#replace _usersFile
			# perhaps should update within the file via sed rather than replacing outright...
			echo "$_currentUsers" > $_usersFile
			nuc=$((nuc+1))
			send2log "	>>> Updated IP address for: $currentMAC -> from: $oldIP - to: $currentIP" 1
		fi
	done < $_connectedUsers
	[ "$nrc" -gt "0" ] && send2log "	>>> Number of rule changes: $nrc" 1
	[ "$nuc" -gt "0" ] && send2log "	>>> Number of user changes: $nuc" 1
}
setdates(){
 	day=`date +%d`
	cMonth=`date +%m`
	rMonth=`date +%m`
	rYear=`date +%Y`
	if [ "$_cDay" -lt "$_ispBillingDay" ] ; then
		rMonth=`expr $rMonth '-' 1`
		if [ "$rMonth" = "0" ] ; then
			rMonth=12
			rYear=`expr $rYear '-' 1`
		else
			rMonth=$(printf %02d $rMonth)
		fi
	fi
	rday=$(printf %02d $_ispBillingDay)
}
#Add chain rules to IPs and MACs
updateUsage()
{
	send2log '=== Update usage === '"($_iteration)" 0
	setdates
	_macUsageDB="$_baseDir$_dataDir$rday-$rMonth-$rYear-$_usageFileName"
	if [ ! -s "$_macUsageDB" ]; then
		send2log '  >>> MAC usage file not found: '"$_macUsageDB"'... created empty file' 2
		touch $_macUsageDB
	fi
	send2log "	--- Reading data from $_macUsageDB" 0
	_usageData=`cat "$_macUsageDB"`
	rHour=`date +%H`
	inUnlimited=0
	if [ "$_unlimited_usage" == 1 ]; then
		currTime=$(date +%s);
		lower=$(date +%s --date="$_unlimited_start");
		upper=$(date +%s --date="$_unlimited_end");
		[ "$currTime" -ge "$lower" ] && [ "$currTime" -lt "$upper" ] && inUnlimited=1
	fi

	if [ "$_doHourlyData" = "1" ]; then
		_hourlyUsageDB="$_baseDir$_dataDir$day-$cMonth-$rYear-$_hourlyFileName"
		if [ ! -s "$_hourlyUsageDB" ]; then
			send2log '  >>> Hourly usage file not found: '"$_hourlyUsageDB"'... created empty file' 2
			touch $_hourlyUsageDB
		fi
		send2log "	--- Reading data from $_hourlyUsageDB" 0
		_hourlyData=`cat "$_hourlyUsageDB"`
	fi
	iptablesData=`iptables -L "$ACMON_RULE" -vnxZ`

	#traff daemon
	if [ "$_traff_daemon" -eq 1 ]; then
		traff=`nvram show 2>&1 | grep traff-"$cMonth"-"$rYear" | cut -d= -f2 | cut -d' ' -f"$day"`
		send2log "=== traff -> $traff" 0
		traffMAC="FF:FF:FF:FF:FF:FF"
		traffIP=""
		traffLine=`echo "$_usageData" | grep -i "$traffMAC,.*,.*,.*,$day"`
		traffDown=`echo "$traff" | cut -d: -f1`
		traffUp=`echo "$traff" | cut -d: -f2`
		traffUsage="$traffMAC,$traffIP,$traffDown,$traffUp,$day"
		if [ -n "$traffLine" ] ; then
			_usageData=`echo "$_usageData" | sed "s/$traffMAC,.*,.*,.*,$day/$traffUsage/"`
			echo "$_usageData" > $_macUsageDB
			send2log "  >>> Update daily $traffMAC  -> down: $traffDown & up: $traffUp [MBytes]" 1
		else
			if [ -z "$_usageData" ] ; then
				send2log "  +++ New daily file: $traffMAC -> down: $traffDown & up: $traffUp [MBytes]" 1
				echo "$traffUsage" > $_macUsageDB
				_usageData="$traffUsage"
			else
				send2log "  +++ New daily line: $traffMAC -> down: $traffDown & up: $traffUp [MBytes]" 1
				echo "$traffUsage" >> $_macUsageDB
				_usageData="$_usageData
$traffUsage"
			fi
		fi

		pndMAC="PROC:NET:DEV"
		pndIP=""
		pndLine=`echo "$_usageData" | grep -i "$pndMAC,.*,.*,.*,$day"`

		br0=`grep $(nvram get lan_ifname) /proc/net/dev`
		dd=`echo "$br0" | cut -d: -f2`
		dd2=`echo $dd | sed -e 's/[ ]+/\*/g'`
		cpndDown=`echo "$dd2" | cut -d' ' -f9`
		cpndUp=`echo "$dd2" | cut -d' ' -f1`
		[ -z $opndDown ] && opndDown=$cpndDown
		[ -z $opndUp ] && opndUp=$cpndUp

		if [ "$_useBC" -eq 1 ]; then
			if [ "$cpndDown" -lt "$opndDown" ]; then
				cpndDown=`echo 'scale=2;'"$cpndDown + 4294967296" | bc`
				send2log "  !!! proc/net/dev downloads rolled over 4GB" 2
			fi
			if [ "$cpndUp" -lt "$opndUp" ]; then
				cpndUp=`echo 'scale=2;'"$cpndUp + 4294967296" | bc`
				send2log "  !!! proc/net/dev uploads rolled over 4GB" 2
			fi
			_pndDown=`echo 'scale=2;'"$_pndDown + $cpndDown - $opndDown" | bc`
			_pndUp=`echo 'scale=2;'"$_pndUp + $cpndUp - $opndUp" | bc`
		else
			_pndDown=`expr $_pndDown + $cpndDown - $opndDown`
			_pndUp=`expr $_pndUp + $cpndUp - $opndUp`
		fi
		pndUsage="$pndMAC,$pndIP,$_pndDown,$_pndUp,$day"
		send2log "  >>> proc/net/dev -> down: $_pndDown += $cpndDown - $opndDown & up: $_pndUp += $cpndUp - $opndUp [Bytes]" 1
		if [ -n "$pndLine" ] ; then
			_usageData=`echo "$_usageData" | sed "s/$pndMAC,.*,.*,.*,$day/$pndUsage/"`
			echo "$_usageData" > $_macUsageDB
			send2log "  >>> Update daily $pndMAC -> down: $_pndDown & up: $_pndUp [Bytes]" 1
		else
			if [ -z "$_usageData" ] ; then
				send2log "  +++ New daily file: $pndMAC -> down: $_pndDown & up: $_pndUp [Bytes]" 1
				echo "$pndUsage" > $_macUsageDB
				_usageData="$pndUsage"
			else
				send2log "  +++ New daily line: $pndMAC -> down: $_pndDown & up: $_pndUp [Bytes]" 1
				echo "$pndUsage" >> $_macUsageDB
				_usageData="$_usageData
$pndUsage"
			fi
		fi
		opndDown=$cpndDown
		opndUp=$cpndUp
	fi

	while read currentIP type flags currentMAC mask iface
	do
		if [ "$iface" != "$LAN_IFACE" ] ; then continue; fi
		if [ "$type" == "0x0" ] || [ "$flags" == "0x0" ] ; then continue; fi
		if [ "$currentMAC" == "00:00:00:00:00:00" ] ; then
			send2log "  >>> Null MAC address for $currentIP not added" 0
			continue
		fi

		currentLine=`echo "$_usageData" | grep -i "$currentMAC,.*,.*,.*,$day"`

		usageIn=`echo "$iptablesData" | awk '{print $9,$2}' | grep "$currentIP " | awk '{print $2}'`
		usageOut=`echo "$iptablesData" | awk '{print $8,$2}' | grep "$currentIP " | awk '{print $2}'`
		[ -z $usageIn ] && usageIn='0'
		[ -z $usageOut ] && usageOut='0'

		if [ "$_unlimited_usage" == 1 ]; then
			currentLine=`echo "$_usageData" | grep -i "$currentMAC,.*,.*,.*,$day,.*,.*"`
			unlimitedIn=`echo "$currentLine" | cut -d, -f6`
			unlimitedOut=`echo "$currentLine" | cut -d, -f7`
			[ -z $unlimitedIn ] && unlimitedIn='0'
			[ -z $unlimitedOut ] && unlimitedOut='0'
		fi

		if [ "$usageIn" = "0" ] && [ "$usageOut" = "0" ];  then		#Nothing to update
			sleep 0
		elif [ -n "$currentLine" ] ; then		#Update an existing line

			send2log "  >>> Update daily $currentMAC -> down: $usageIn & up: $usageOut [bytes]" 1
			dbUsageIn=`echo "$currentLine" | cut -d, -f3`
			dbUsageOut=`echo "$currentLine" | cut -d, -f4`
			[ -z $dbUsageIn ] && dbUsageIn='0'
			[ -z $dbUsageOut ] && dbUsageOut='0'
			#Determine the new usage with option to use `bc` for integer overflow issues
			if [ "$_useBC" -eq 1 ]; then
				dbUsageIn=`echo 'scale=2;'"$dbUsageIn + $usageIn" | bc`
				dbUsageOut=`echo 'scale=2;'"$dbUsageOut + $usageOut" | bc`
			else
				dbUsageIn=`expr $dbUsageIn + $usageIn`
				dbUsageOut=`expr $dbUsageOut + $usageOut`
			fi

			if [ "$inUnlimited" == "1" ]; then
				send2log "  >>> Unlimited usage time - $usageIn & $usageOut" 1
				if [ "$_useBC" -eq 1 ]; then
					unlimitedIn=`echo 'scale=2;'"$unlimitedIn + $usageIn" | bc`
					unlimitedOut=`echo 'scale=2;'"$unlimitedOut + $usageOut" | bc`
				else
					unlimitedIn=`expr $unlimitedIn + $usageIn`
					unlimitedOut=`expr $unlimitedOut + $usageOut`
				fi
			fi
			if [ "$_unlimited_usage" == 1 ] ; then
				newUsage="$currentMAC,,$dbUsageIn,$dbUsageOut,$day,$unlimitedIn,$unlimitedOut"
				_usageData=`echo "$_usageData" | sed "s/$currentMAC,.*,.*,.*,$day,.*,.*/$newUsage/"`
			else
				newUsage="$currentMAC,,$dbUsageIn,$dbUsageOut,$day"
				_usageData=`echo "$_usageData" | sed "s/$currentMAC,.*,.*,.*,$day/$newUsage/"`
			fi
			echo "$_usageData" > $_macUsageDB
		else		#Add a new line
			if [ "$inUnlimited" == "1" ]; then
				newUsage="$currentMAC,,$usageIn,$usageOut,$day,$usageIn,$usageOut"
			elif [ "$_unlimited_usage" == 1 ]; then
				newUsage="$currentMAC,,$usageIn,$usageOut,$day,0,0"
			else
				newUsage="$currentMAC,,$usageIn,$usageOut,$day"
			fi
			if [ -z "$_usageData" ] ; then
				send2log "  +++ New daily file: $currentMAC -> down: $usageIn & up: $usageOut [bytes]" 1
				echo "$newUsage" > $_macUsageDB
				_usageData="$newUsage"
			else
				send2log "  +++ New daily line: $currentMAC -> down: $usageIn & up: $usageOut [bytes]" 1
				echo "$newUsage" >> $_macUsageDB
				_usageData="$_usageData
$newUsage"
			fi
		fi

	#hourly
		if [ "$_doHourlyData" = "1" ]; then
			hLine=`echo "$_hourlyData" | grep -i "$currentMAC,.*,.*,.*,$rHour"`
			if [ "$usageIn" = "0" ] && [ "$usageOut" = "0" ]; then
				sleep 0
			elif [ -n "$hLine" ] ; then
				send2log "  >>> Update hourly $currentMAC -> down: $usageIn & up: $usageOut [bytes]" 1
				dbHourIn=`echo "$hLine" | cut -d, -f3`
				dbHourOut=`echo "$hLine" | cut -d, -f4`
				[ -z "$dbHourIn" ] && dbHourIn='0'
				[ -z "$dbHourOut" ] && dbHourOut='0'
				#Determine the new usage with option to use `bc` for integer overflow issues
				if [ "$_useBC" -eq 1 ]; then
					dbHourIn=`echo 'scale=2;'"$dbHourIn + $usageIn" | bc`
					dbHourOut=`echo 'scale=2;'"$dbHourOut + $usageOut" | bc`
				else
					dbHourIn=`expr $dbHourIn + $usageIn`
					dbHourOut=`expr $dbHourOut + $usageOut`
				fi
				newHUsage="$currentMAC,,$dbHourIn,$dbHourOut,$rHour"
				#Update the existing line
				_hourlyData=`echo "$_hourlyData" | sed "s/$currentMAC,.*,.*,.*,$rHour/$newHUsage/"`
				echo "$_hourlyData" > $_hourlyUsageDB
			else
				newHUsage="$currentMAC,,$usageIn,$usageOut,$rHour"
				if [ -z "$_hourlyData" ] ; then
					send2log "  +++ New hourly file: $currentMAC -> down: $usageIn & up: $usageOut [bytes]" 1
					echo "$newHUsage" > $_hourlyUsageDB
					_hourlyData="$newHUsage"
				else
					send2log "  +++ New hourly line: $currentMAC -> down: $usageIn & up: $usageOut [bytes]" 1
					echo "$newHUsage" >> $_hourlyUsageDB
					_hourlyData="$_hourlyData
$newHUsage"
				fi
			fi
		fi

	done < $_connectedUsers
}

publishData()
{
	send2log "=== Publishing Usage ===" 0
	#set the date of the output file...
	cday=`date +%d`
	cMonth=`date +%m`
	rMonth=`date +%m`
	rYear=`date +%Y`

	if [ "$_cDay" -lt "$_ispBillingDay" ] ; then
		rMonth=`expr $rMonth '-' 1`
		if [ "$rMonth" = "0" ] ; then
			rMonth=12
			rYear=`expr $rYear '-' 1`
		else
			rMonth=$(printf %02d $rMonth)
		fi
	fi
	rday=$(printf %02d $_ispBillingDay)
	_macUsageDB="$_baseDir$_dataDir$rday-$rMonth-$rYear-$_usageFileName"
	_macUsageWWW="$_wwwPath$_wwwData$rday-$rMonth-$rYear-$_usageFileName"
	copyfiles "$_macUsageDB" "$_macUsageWWW"

	_savedconfigMd5="$_configMd5"
	if [ "$_doHourlyData" = "1" ]; then
		_hourlyUsageDB="$_baseDir$_dataDir$cday-$cMonth-$rYear-$_hourlyFileName"
		_hourlyUsageWWW="$_wwwPath$_wwwData$cday-$cMonth-$rYear-$_hourlyFileName"
		copyfiles "$_hourlyUsageDB" "$_hourlyUsageWWW"
	fi
}
doliveUpdates()
{
	send2log "=== doliveUpdates === " 0
	if [ -f "$_liveFilePath" ]; then
		rm "$_liveFilePath"
		touch "$_liveFilePath"
	fi
 	cDay=`date +%d`
	cMonth=`date +%m`
	cYear=`date +%Y`
	cTime=`date +"%T"`
	echo "var last_update='$cYear/$cMonth/$cDay $cTime'" > $_liveFilePath
	loadavg=`echo cat /proc/loadavg`
	meminfo=`echo cat /proc/meminfo`
	load1=`$loadavg | awk '{print $1}'`
	load5=`$loadavg | awk '{print $2}'`
	load15=`$loadavg | awk '{print $3}'`
	freeMem=`$meminfo | awk '/MemFree/ { print $2 }'`
	totMem=`$meminfo | awk '/MemTotal/ { print $2 }'`
	echo "var load1=$load1,load5=$load5,load15=$load15,freeMem=$freeMem,totMem=$totMem" >> $_liveFilePath

	awk 'BEGIN { printf "var curr_connections=["} { gsub(/(src|dst|sport|dport)=/, ""); printf "['\''%s'\'','\''%s'\'','\''%s'\'','\''%s'\'','\''%s'\''],",$1,$1 == "tcp" ? $5 : $4,$1 == "tcp" ? $7 : $6,$1 == "tcp" ? $6 : $5,$1 == "tcp" ? $8 : $7; } END { print "[null]]"}' /proc/net/ip_conntrack >> $_liveFilePath

	iptablesData=`iptables -L "$LIVE_RULE" -vnxZ`
	newUsage=""
	comma=""
	LAN_IFACE=`nvram get lan_ifname`
	while read currentIP type flags currentMAC mask iface
	do
		if [ "$iface" != "$LAN_IFACE" ] ; then continue; fi
		if [ "$currentMAC" == "00:00:00:00:00:00" ] ; then continue; fi

		usageIn=`echo "$iptablesData" | awk '{print $9,$2}' | grep "$currentIP " | awk '{print $2}'`
		#usageIn=`echo "$iptablesData" | awk '$9 == "$currentIP" {print $2}'`
		usageOut=`echo "$iptablesData" | awk '{print $8,$2}' | grep "$currentIP " | awk '{print $2}'`
		#usageOut=`echo "$iptablesData" | awk '$8 == "$currentIP" {print $2}'`
		if [ "$usageIn" -gt 0 ] || [ "$usageOut" -gt 0 ] ; then
			newUsage="$newUsage$comma['$currentMAC',$usageIn,$usageOut]"
			comma=','
		fi
	done < $_connectedUsers
	echo "curr_users=[" "$newUsage" "]" >> $_liveFilePath
}
updateUsers()
{
	send2log "=== Check for User updates === " 0
	_usersMd5=`md5sum $_usersFile | awk '{print $1}'`
	if [ "$_usersMd5" != "$_savedusersMd5" ] ; then
		_currentUsers=`cat "$_usersFile"`
		if [ -z "$_currentUsers" ]; then
			send2log "No Clients found in User File: $_usersFile" 2
		fi
		send2log "  >>> Users file ($_usersFile) was changed" 2
		copyfiles "$_usersFile" "$_usersFileWWW"
	else
		send2log "  >>> No change" 0
	fi
	_savedusersMd5=$_usersMd5
	if [ ! -s "$_usersFileWWW" ] ; then
		copyfiles "$_usersFile" "$_usersFileWWW"
	fi
	if [ ! -s "$_macUsageWWW" ] ; then
		publishData
	fi
}

dailyBU()
{
	cMonth=`date +%m`
	pMonth=`date +%m`
	pYear=`date +%Y`
	if [ "$_cDay" -eq "1" ] ; then
		pMonth=`expr $pMonth '-' 1`
		if [ "$pMonth" = "0" ] ; then
			pMonth=12
			pYear=`expr $pYear '-' 1`
		else
			pMonth=$(printf %02d $pMonth)
		fi
	fi
	send2log "=== Daily backup for $_pDay-$pMonth-$pYear ===" 1
	if [ "${_dailyBUPath:0:1}" = "/" ] ; then
		bupath=$_dailyBUPath
	else
		bupath=$_baseDir$_dailyBUPath
	fi
	if [ ! -d "$bupath" ] ; then
		send2log "  >>> Creating Daily BackUp directory - $bupath" 1
		mkdir -p "$bupath"
	fi
	rday=$(printf %02d $_ispBillingDay)
	_macUsageDB="$_baseDir$_dataDir$rday-$pMonth-$pYear-$_usageFileName"
	macUsageBU="$bupath$_pDay-$pMonth-$pYear-$_usageFileName"
	userBU="$bupath$_pDay-$pMonth-$pYear-$_usersFileName"
	copyfiles "$_usersFile" "$userBU"

	copyfiles "$_macUsageDB" "$macUsageBU"

	if [ "$_doHourlyData" = "1" ]; then
		hourlyUsageBU="$bupath$_pDay-$cMonth-$pYear-$_hourlyFileName"
		copyfiles "$_hourlyUsageDB" "$hourlyUsageBU"
	fi
	if [ "$_tarBUs" = "1" ]; then
		cd "$bupath"
		sleep 5
		send2log "  >>> Compressed back-ups for $_pDay-$pMonth-$pYear to $bupath"'bu-'"$_pDay-$pMonth-$pYear.tar.gz" 2
		tar -czf "bu-$pYear-$pMonth-$_pDay.tar.gz" "$_pDay-$pMonth-$pYear-*"
		return=$?
		if [ "$return" -ne "0" ] ; then
			send2log "  >>> Back-up compression for $_pDay-$pMonth-$pYear failed! Tar returned $return" 2
		else
			send2log "  >>> Back-ups for $_pDay-$pMonth-$pYear compressed - tar exited successfully." 1
			rm "$_pDay-$pMonth-$pYear-*"
			return=$?
			send2log "  >>> Back-ups for $_pDay-$pMonth-$pYear removed." 1
		fi
		cd "/"
	fi
}

# ==========================================================
#				  Main program
# ==========================================================
_lockDir=/tmp/ACMON-lock
if [ ! -d "$_lockDir" ] ; then
	mkdir "$_lockDir"
   echo "
---------------------------------------
Starting the Yet Another Monitor script
version: $_version
=======================================
"
else
	echo "*** Another instance of this script is already running!!!"
	echo "*** You must either run 'rm /tmp/ac_mon.lock' or run 'yamon.shutdown' to launch this script again"
	exit 0
fi
ni=`top -b -n 1 | grep -c yamon`
echo "*** $ni instance(s) of YAMon are running.  NB - Two is OK... the script itself plus this child process to count the number of instances)"
if [ "$ni" -gt "2" ] ; then
	echo "*** You must either run 'rm /tmp/ac_mon.lock' or run 'yamon.shutdown' to launch this script again"
	rmdir "$_lockDir"
	exit 0
fi

started=false
#set _configFile to the first parameter passed to the script
_configFile=$1
setDefaults
readConfig
started=true
updateUsers

_iteration=0
# main loop... to break the loop either edit config.file or delete _lockDir (/tmp/ac_mon.lock)
while [ "$_monitoring" = "1" ] && [ -d $_lockDir ]; do
	_iteration=$(($_iteration%($_updateInterval*$_publishInterval) + 1))
	if [ "$_paused" = "0" ] ; then
		setupIPRules
		updateUsers
		sleep "$_updatefreq"
		if [ "$_doLiveUpdates" -eq "1" ]; then
			doliveUpdates
		fi
		#Check for an update
		if [ $(($_iteration%$_updateInterval)) -eq 0 ]; then
			updateUsage
		fi
		#Check for a publish
		if [ $(($_iteration%$_publishInterval)) -eq 0 ]; then
			publishData
		fi
	fi
	#Check to see whether config.file has changed
	readConfig
	#Check to see whether the date has changed
	_cDay=`date +%d`
	if [ "$_doDailyBU" = "1" ] && [ "$_cDay" != "$_pDay" ] ;  then
		dailyBU
		# clear the pdn variables so that the day starts at zero again
		unset -v opndDown
		unset -v opndUp
		_pndDown=0
		_pndUp=0
	fi
	_pDay="$_cDay"
	# Commented out because not the ps call is not well supported across all firmware builds
	# ni=`ps cax | grep -c yamon`
	# "  >>> Number of YAMon instances: $ni." 0
	# if [ $ni -gt 2 ]; then
	#	send2log "  !!! Incorrect number of YAMon instances???: $ni." 2
	# fi

	#one last backup before shutting down
	if [ "$_monitoring" = "0" ] || [ ! -d $_lockDir ]; then
		[ -d $_lockDir ] && rmdir $_lockDir
		copyfiles "$_wwwPath" "$_baseDir$_wwwBU" 
		send2log "
=====================================
Stopped AC Monitor script
-------------------------------------
" 2
		echo "
=====================================
Stopped AC Monitor script [screen]
-------------------------------------
"
		kill yamon.sh
		sleep 10
	 fi
done &
